﻿using Microsoft.AspNetCore.Authentication;
using Microsoft.IdentityModel.Protocols.OpenIdConnect;

namespace Soul.IdentityServer.Validation
{
    public class ClientSecretValidator : IClientSecretValidator
    {
        private readonly ISystemClock _clock;
        private readonly IClientStore _clientStore;

        public ClientSecretValidator(ISystemClock clock, IClientStore clientStore)
        {
            _clock = clock;
            _clientStore = clientStore;
        }

        public async Task<Client> ValidationAsync(OpenIdConnectParameters parameters)
        {
            parameters.Validate(OpenIdConnectParameterNames.ClientId);
            var client = await _clientStore.FindClientAsync(parameters.ClientId!);
            if (client == null)
            {
                throw new ValidationException(ValidationErrors.InvalidClient);
            }
            if (client.RequireSecret)
            {
                parameters.Validate(OpenIdConnectParameterNames.ClientSecret);
                ValidationClientSecrets(client, parameters.ClientSecret!);
            }
            return client;
        }

        private void ValidationClientSecrets(Client client, string secret)
        {
            var secretValues = new string[]
            {
                secret.Sha256(),
                secret.Sha512(),
            };

            var clientSecrets = client.ClientSecrets.Where(a => secretValues.Contains(a.Value));

            if (!clientSecrets.Any(a => a.Expiration == null || a.Expiration > _clock.UtcNow.UtcDateTime))
            {
                throw new ValidationException(ValidationErrors.InvalidClientSecret);
            }
        }
    }
}
